<html>
    <head>
        <title>数据库配置  Database configurations</title>
    </head>
    <body>
        <script>
            //  分层解决方案  :   数据库配置


                        /*
                                ABP Studio的分层解决方案模板包括预配置的数据库设置。本文档介绍了如何管理解决方案中的数据库配置。
                        */

                        /*
                            一、连接字符串  Connection Strings

                                        连接字符串存储在appsettings.json文件中。

                                        您可以通过修改相应的appsettings.json文件来为不同的环境自定义它们。

                                        DbMigrator项目和Web应用程序项目之一默认使用Default连接字符串。


                                        要更改Default键的连接字符串，请更新项目中的appsettings.json文件。
                                        
                                        连接字符串在ConnectionStrings部分下定义，如下所示：

                                                {
                                                    "ConnectionStrings": {
                                                        "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=Bookstore;Trusted_Connection=True;TrustServerCertificate=true"
                                                    }
                                                }

                        */

                        /*
                            二、DbContext类

                                        在*.EntityFrameworkCore项目中，定义了DbContext类。
                                        
                                    1、创建DbContext类 

                                                    DbContext类派生自AbpDbContext类，该类是ABP框架的一部分。



                                                            eg:

                                                                    [ReplaceDbContext(typeof(IIdentityProDbContext))]
                                                                    [ReplaceDbContext(typeof(ISaasDbContext))]
                                                                    [ConnectionStringName("Default")]
                                                                    public class BookstoreDbContext :
                                                                        AbpDbContext<BookstoreDbContext>,
                                                                        ISaasDbContext,
                                                                        IIdentityProDbContext
                                                                    {
                                                                        #region 依赖模块中的实体

                                                                            // Identity
                                                                            public DbSet<IdentityUser> Users { get; set; }
                                                                            public DbSet<IdentityRole> Roles { get; set; }
                                                                            public DbSet<IdentityClaimType> ClaimTypes { get; set; }
                                                                            public DbSet<OrganizationUnit> OrganizationUnits { get; set; }
                                                                            public DbSet<IdentitySecurityLog> SecurityLogs { get; set; }
                                                                            public DbSet<IdentityLinkUser> LinkUsers { get; set; }
                                                                            public DbSet<IdentityUserDelegation> UserDelegations { get; set; }
                                                                            public DbSet<IdentitySession> Sessions { get; set; }

                                                                            // SaaS
                                                                            public DbSet<Tenant> Tenants { get; set; }
                                                                            public DbSet<Edition> Editions { get; set; }
                                                                            public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }

                                                                        #endregion

                                                                        public BookstoreDbContext(DbContextOptions<BookstoreDbContext> options)
                                                                            : base(options)
                                                                        {

                                                                        }

                                                                        // 创建数据库模型
                                                                        protected override void OnModelCreating(ModelBuilder builder)
                                                                        {
                                                                            base.OnModelCreating(builder);

                                                                            builder.ConfigurePermissionManagement();
                                                                            builder.ConfigureSettingManagement();
                                                                            builder.ConfigureBackgroundJobs();
                                                                            builder.ConfigureAuditLogging();
                                                                            builder.ConfigureFeatureManagement();
                                                                            builder.ConfigureIdentityPro();
                                                                            builder.ConfigureOpenIddictPro();
                                                                            builder.ConfigureLanguageManagement();
                                                                            builder.ConfigureSaas();
                                                                            builder.ConfigureTextTemplateManagement();
                                                                            builder.ConfigureGdpr();
                                                                            builder.ConfigureCmsKit();
                                                                            builder.ConfigureCmsKitPro();
                                                                            builder.ConfigureBlobStoring();
                                                                            
                                                                            // 在此处配置你自己的实体

                                                                                builder.Entity<YourEntity>(b =>
                                                                                {
                                                                                    b.ToTable(BookstoreConsts.DbTablePrefix + "YourEntities", BookstoreConsts.DbSchema);
                                                                                    b.ConfigureByConvention(); //auto configure for the base class props
                                                                                });
                                                                        }
                                                                    }


                                    2、[ConnectionStringName]特性

                                                  我们在BookstoreDbContext类中使用Default连接字符串。您可以通过更新ConnectionStringName属性来更改连接字符串名称。
                                                  
                                                        [ConnectionStringName("Default")]

                                                 ConnectionStringName属性定义了该DbContext类正在使用的连接字符串的唯一名称。

                                                 它与appsettings.json文件中定义的连接字符串匹配。

                                                 该名称也用于数据库迁移以区分不同的数据库结构，并在为多租户系统存储租户连接字符串时用作键。


                                    3、[ReplaceDbContext] 特性

                                                应用程序DbContext利用Identity和Saas*模块并创建一个包含这些模块数据库模式的单个数据库。

                                                这些模块通常定义自己的DbContext类。

                                                但是[ReplaceDbContext]特性告诉ABP使用this（BookstoreDbContext）DbContext类而不是这些模块定义的DbContext类。

                                                从技术上讲，它在运行时替换了给定的(依赖模块的)DbContext类。

                                                我们这样做是为了确保我们在处理这些多个模块时拥有单个（合并）数据库模式、单个数据库迁移路径和单个数据库事务操作。

                                                当我们替换某个依赖模块的DbContext时，我们应该实现它DbContext的接口:

                                                            public class BookstoreDbContext :
                                                            AbpDbContext<BookstoreDbContext>,
                                                            ISaasDbContext,
                                                            IIdentityProDbContext

                                                            (该类实现了ISaasDbContext和IIdentityProDbContext，因此这些模块可以使用它。)

                                                作为下一部分，BookstoreDbContext类定义了以下由实现的接口强制的属性:

                                                            // Identity
                                                                public DbSet<IdentityUser> Users { get; set; }
                                                                public DbSet<IdentityRole> Roles { get; set; }
                                                                public DbSet<IdentityClaimType> ClaimTypes { get; set; }
                                                                public DbSet<OrganizationUnit> OrganizationUnits { get; set; }
                                                                public DbSet<IdentitySecurityLog> SecurityLogs { get; set; }
                                                                public DbSet<IdentityLinkUser> LinkUsers { get; set; }
                                                                public DbSet<IdentityUserDelegation> UserDelegations { get; set; }
                                                                public DbSet<IdentitySession> Sessions { get; set; }

                                                            // SaaS
                                                                public DbSet<Tenant> Tenants { get; set; }
                                                                public DbSet<Edition> Editions { get; set; }
                                                                public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }


                                  4、OnModelCreating方法

                                            OnModelCreating方法用于配置数据库模型。
                                            
                                            它调用ABP框架的Configure*方法来配置模块的数据库结构。

                                            您还可以在此方法中配置自己的表/实体。

                                                      protected override void OnModelCreating(ModelBuilder builder)
                                                    {
                                                        base.OnModelCreating(builder);

                                                        builder.ConfigurePermissionManagement();
                                                        builder.ConfigureSettingManagement();
                                                        builder.ConfigureBackgroundJobs();
                                                        builder.ConfigureAuditLogging();
                                                        builder.ConfigureFeatureManagement();
                                                        builder.ConfigureIdentityPro();
                                                        builder.ConfigureOpenIddictPro();
                                                        builder.ConfigureLanguageManagement();
                                                        builder.ConfigureSaas();
                                                        builder.ConfigureTextTemplateManagement();
                                                        builder.ConfigureGdpr();
                                                        builder.ConfigureCmsKit();
                                                        builder.ConfigureCmsKitPro();
                                                        builder.ConfigureBlobStoring();
                                                        
                                                        // 此处配置你的实体关系

                                                        //builder.Entity<YourEntity>(b =>
                                                        //{
                                                        //    b.ToTable(BookstoreConsts.DbTablePrefix + "YourEntities", BookstoreConsts.DbSchema);
                                                        //    b.ConfigureByConvention(); //auto configure for the base class props
                                                        //    //...
                                                        //});
                                                    }  

                                            Configure*方法是在每个模块的EntityFrameworkCore项目中定义的扩展方法。

                                            这些方法用于为其各自的模块配置数据库模型。

                                            在运行时，模块的DbContext类仅被使用ReplaceDbContext属性的DbContext类替换。
                                            
                                            对于其他模块，使用它们自己的专用DbContext类而不进行替换。
                        */

                        /*
                            三、数据库DbContext工厂接口  IDesignTimeDbContextFactory 

                                          IDesignTimeDbContextFactory接口用于在设计时创建DbContext实例。
                                          
                                          EF Core工具使用它来创建迁移和更新数据库。

                                          BookstoreDbContextFactory类实现IDesignTimeDbContextFactory接口来创建BookstoreMigrationsDbContext(迁移时使用的数据库上下文)实例。

                                                            public class BookstoreDbContextFactory : IDesignTimeDbContextFactory<BookstoreDbContext>
                                                            {
                                                                // 创建数据库上下文实例
                                                                    public BookstoreDbContext CreateDbContext(string[] args)
                                                                    {
                                                                        var configuration  = BuildConfiguration();
                                                                        BookstoreEfCoreEntityExtensionMappings.Configure(); // 额外属性的映射配置

                                                                        var builder = new DbContextOptionsBuilder<BookstoreDbContext>()
                                                                            .UseSqlServer(configuration.GetConnectionString("Default"));
                                                                        
                                                                        return new BookstoreDbContext(builder.Options);
                                                                    }

                                                                // 获取IConfigurationRoot服务
                                                                    private static IConfigurationRoot BuildConfiguration()
                                                                    {
                                                                        var builder = new ConfigurationBuilder()
                                                                            .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../Acme.Bookstore.DbMigrator/"))
                                                                            .AddJsonFile("appsettings.json", optional: false);

                                                                        return builder.Build();
                                                                    }
                                                            }
                        */

                        /*
                            四、配置

                                    在*.EntityFrameworkCore项目中，BookstoreEntityFrameworkCoreModule类(EFCore项目的模块类)用于配置数据库上下文。

                                             public override void ConfigureServices(ServiceConfigurationContext context)
                                            {
                                                // 将数据库上下文注入IOC
                                                context.Services.AddAbpDbContext<BookstoreDbContext>(options =>
                                                {
                                                    // 移除 includeAllEntities: true 就可以为所有提提实现默认仓储
                                                    options.AddDefaultRepositories(includeAllEntities: true);
                                                });

                                                Configure<AbpDbContextOptions>(options =>
                                                {
                                                    // 此处切换你的数据库提供程序
                                                    options.UseSqlServer();
                                                });
                                                
                                            }                               
                        */

                        /*
                              五、SaaS模块：租户管理UI

                                        Saas 模块提供了必要的UI来设置和更改租户的链接字符并触发数据库迁移。

                                        1、连接字符串管理模式

                                                    您可以单击SaaS模块的租户页面中租户的Actions下拉按钮中的Database Connection Strings按钮，

                                                    它会打开页面让你设置租户的链接字符串。

                                                    在这里，我们可以为租户设置一个默认连接字符串。

                                                    当您进行更改并保存对话框时，数据库会自动创建和迁移。

                                                    如果您稍后更新连接字符串（例如，如果您更改库名），它也会再次触发数据库迁移过程。


                                        2、手动应用数据库迁移

                                                 如果你需要手动触发特定的数据库迁移，请单击相关租户的Actions下拉列表，然后在Saas模块的租户管理页面上选择应用数据库迁移命令：
                                                 
                                                 
                        */
        </script>
    </body>
</html>